import React, { useState } from 'react';
import Header from './components/Header';
import TabBar from './components/TabBar';
import DataInputTab from './components/data/DataInputTab';
import PredictionTab from './components/prediction/PredictionTab';
import EvaluationTab from './components/evaluation/EvaluationTab';
import ProgressBar from './components/training/ProgressBar';
import { AppState } from './types';
import { parseData, preprocessData, splitData } from './services/dataService';
import { createModel, optimizeHyperparameters } from './services/modelService';

function App() {
  const [state, setState] = useState<AppState>({
    data: {
      filePath: '',
      fileName: '',
      columnNames: [],
      selectedColumn: '',
      startRow: 1,
      endRow: 100,
      data: null,
      sequenceLength: 10,
      isLoading: false
    },
    model: {
      config: {
        dim: 64,
        depth: 4,
        heads: 4,
        mlpDim: 128,
        dropout: 0.1,
        learningRate: 0.001,
        batchSize: 32,
        epochs: 20
      },
      isTraining: false,
      isOptimizing: false,
      progress: 0,
      loss: 0,
      accuracy: 0,
      optimizationProgress: 0,
      predictionResult: null,
      evaluationMetrics: null,
      confusionMatrix: null
    },
    activeTab: 'data'
  });

  const handleFileSelect = async (file: File | null) => {
    if (!file) {
      setState(prev => ({
        ...prev,
        data: {
          ...prev.data,
          filePath: '',
          fileName: '',
          columnNames: [],
          selectedColumn: '',
          data: null
        }
      }));
      return;
    }

    setState(prev => ({
      ...prev,
      data: {
        ...prev.data,
        isLoading: true,
        fileName: file.name
      }
    }));

    try {
      const { data, columns } = await parseData(file);
      
      setState(prev => ({
        ...prev,
        data: {
          ...prev.data,
          filePath: URL.createObjectURL(file),
          fileName: file.name,
          columnNames: columns,
          selectedColumn: columns[0],
          data,
          endRow: Math.min(prev.data.endRow, data.length),
          isLoading: false
        }
      }));
    } catch (error) {
      console.error('Error parsing file:', error);
      setState(prev => ({
        ...prev,
        data: {
          ...prev.data,
          isLoading: false
        }
      }));
      alert('Failed to parse file. Please check the file format.');
    }
  };

  const handleUpdateData = (updates: Partial<AppState['data']>) => {
    setState(prev => ({
      ...prev,
      data: {
        ...prev.data,
        ...updates
      }
    }));
  };

  const handleUpdateModelConfig = (updates: Partial<AppState['model']['config']>) => {
    setState(prev => ({
      ...prev,
      model: {
        ...prev.model,
        config: {
          ...prev.model.config,
          ...updates
        }
      }
    }));
  };

  const handleStartAnalysis = async () => {
    const { data, model } = state;
    
    if (!data.data || data.data.length === 0) {
      alert('No data available for analysis');
      return;
    }
    
    setState(prev => ({
      ...prev,
      model: {
        ...prev.model,
        isTraining: true,
        progress: 0,
        loss: 1.0,
        accuracy: 0
      }
    }));
    
    try {
      // Preprocess data
      const { features, diffFeatures, labels } = preprocessData(
        data.data,
        data.sequenceLength,
        data.startRow,
        data.endRow
      );
      
      // Split into training and validation sets
      const [trainFeatures, valFeatures] = splitData(features);
      const [trainDiffFeatures, valDiffFeatures] = splitData(diffFeatures);
      const [trainLabels, valLabels] = splitData(labels);
      
      // Create and train model
      const mockModel = createModel(model.config);
      
      await mockModel.train(
        trainFeatures,
        trainDiffFeatures,
        trainLabels,
        (progress, loss, accuracy) => {
          setState(prev => ({
            ...prev,
            model: {
              ...prev.model,
              progress,
              loss,
              accuracy
            }
          }));
        }
      );
      
      // Generate prediction for the last sequence
      const lastFeature = features[features.length - 1];
      const lastDiffFeature = diffFeatures[diffFeatures.length - 1];
      const predictionResult = mockModel.predict(lastFeature, lastDiffFeature);
      
      // Generate mock confusion matrix and evaluation metrics
      const confusionMatrix = mockModel.generateConfusionMatrix();
      const evaluationMetrics = {
        accuracy: 0.82,
        topKAccuracy: 0.94,
        f1Score: 0.81,
        precision: 0.83,
        recall: 0.80
      };
      
      // Update state with results
      setState(prev => ({
        ...prev,
        model: {
          ...prev.model,
          isTraining: false,
          predictionResult,
          evaluationMetrics,
          confusionMatrix
        },
        activeTab: 'prediction'
      }));
      
    } catch (error) {
      console.error('Error during analysis:', error);
      setState(prev => ({
        ...prev,
        model: {
          ...prev.model,
          isTraining: false
        }
      }));
      alert('An error occurred during analysis.');
    }
  };

  const handleOptimizeHyperparams = async () => {
    const { data } = state;
    
    if (!data.data || data.data.length === 0) {
      alert('No data available for hyperparameter optimization');
      return;
    }
    
    setState(prev => ({
      ...prev,
      model: {
        ...prev.model,
        isOptimizing: true,
        optimizationProgress: 0
      }
    }));
    
    try {
      // Preprocess data
      const { features, diffFeatures, labels } = preprocessData(
        data.data,
        data.sequenceLength,
        data.startRow,
        data.endRow
      );
      
      // Run optimization
      const optimizedConfig = await optimizeHyperparameters(
        features,
        diffFeatures,
        labels,
        (progress) => {
          setState(prev => ({
            ...prev,
            model: {
              ...prev.model,
              optimizationProgress: progress
            }
          }));
        }
      );
      
      // Update state with optimized config
      setState(prev => ({
        ...prev,
        model: {
          ...prev.model,
          isOptimizing: false,
          config: optimizedConfig
        }
      }));
      
      alert('Hyperparameter optimization complete!');
      
    } catch (error) {
      console.error('Error during hyperparameter optimization:', error);
      setState(prev => ({
        ...prev,
        model: {
          ...prev.model,
          isOptimizing: false
        }
      }));
      alert('An error occurred during hyperparameter optimization.');
    }
  };

  const handleTabChange = (tab: AppState['activeTab']) => {
    setState(prev => ({
      ...prev,
      activeTab: tab
    }));
  };

  return (
    <div className="min-h-screen bg-gray-50 flex flex-col">
      <Header />
      
      <TabBar activeTab={state.activeTab} onTabChange={handleTabChange} />
      
      <div className="flex-1">
        {/* Progress bars */}
        <div className="container mx-auto mt-4 px-4">
          <div className="space-y-4">
            <ProgressBar 
              progress={state.model.progress} 
              label="Training Progress" 
              isVisible={state.model.isTraining} 
            />
            
            <ProgressBar 
              progress={state.model.optimizationProgress} 
              label="Hyperparameter Optimization" 
              isVisible={state.model.isOptimizing} 
            />
          </div>
        </div>
        
        {/* Active tab content */}
        <div className="container mx-auto">
          {state.activeTab === 'data' && (
            <DataInputTab
              data={state.data}
              onUpdateData={handleUpdateData}
              onFileSelect={handleFileSelect}
              onStartAnalysis={handleStartAnalysis}
              onOptimizeHyperparams={handleOptimizeHyperparams}
              isTraining={state.model.isTraining}
              isOptimizing={state.model.isOptimizing}
            />
          )}
          
          {state.activeTab === 'prediction' && (
            <PredictionTab
              model={state.model}
              data={state.data}
            />
          )}
          
          {state.activeTab === 'evaluation' && (
            <EvaluationTab
              model={state.model}
            />
          )}
        </div>
      </div>
    </div>
  );
}

export default App;